from flask import current_app
from flask import make_response
from flask import request, jsonify
from re import match

from flask import session

from info import constants, db
from info import redis_store
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from info.utils.yuntongxun.sms import CCP
from . import passport_blu
import random


@passport_blu.route("/image_code")
def image_code():
    """
    这个函数用来处理图片验证码的请求

    """
    # 1 获取参数 判空
    image_code_id = request.args.get("image_code_id")

    if not image_code_id:
        return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")
        # 2 生成图片
        # 调用captcha的generate_captcha方法,这个方法返回三个数据，
        # 第一个是图片的名称，第二个是验证码文本，第三个是验证码图片的内容
    name, text, content = captcha.generate_captcha()

    # 3保存图片验证码信息到redis
    try:
        redis_store.set("IMAGE_CODE_" + image_code_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="数据错误")

    # 4 返回图片验证码
    response = make_response(content)
    response.headers["Content-Type"] = "image/jpg"
    return response


# 处理发送短信验证码的  请求
@passport_blu.route("/sms_code", methods=["POST"])
def sms_code():
    """
       这个函数用来处理 发送短信验证码 的请求

       业务逻辑
       1、获取参数、判空
           (手机号、用户输入的图片验证码和image_code_id)
           验证手机是不是符合格式
       2、对比redis中的图片文本跟用户输入的是否一样
       2.1 获取redis中的图片文本信息(根据image_code_id作为键来获取的)
       2.2 如果用户输入的图片验证码 和 2.1获取到的文本信息不一致，return
       3、发送验证码
       3.1 查询数据库（根据手机号查询用户表User） 如果存在user用户，要return
       3.2 生成随机短信验证码， 发送短信内容
       3.3 保存短信验证码到redis中 (以手机号码为键，真实短信验证码为值)
       3.4 返回结果给浏览器
       """
    # 1 获取  参数 手机号  图片验证码内容和图片uuid
    parma_dict = request.json
    mobile = parma_dict.get("mobile")
    image_code = parma_dict.get("image_code")
    image_code_id = parma_dict.get("image_code_id")
    if not all([mobile, image_code, image_code_id]):
        return jsonify(error=RET.PARAMERR, errmsg="缺少参数")

    # 验证手机号
    if not match(r"^1[7835]\d{9}$", mobile):
        return jsonify(error=RET.DATAERR, errmsg="手机格式不正确")

    # 验证图片验证码和uuid
    try:
        real_image_code = redis_store.get("IMAGE_CODE_" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取图片验证码失败")

    if real_image_code.decode().lower() != image_code.lower():
        return jsonify(errno=RET.DATAERR, errmsg="输入的图片验证码错误")

    # 发送验证码 看看这个用户是不是已经注册  没有就发送验证码
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(error=RET.DATAERR, errmsg="数据库操作失败")
    if user:
        return jsonify(error=RET.DATAERR, errmsg="该手机号码已经被注册")

    # 发送短信验证码    先生成六位随机数字
    ret = random.randint(0, 999999)
    sms_code = "%06d" % ret
    print(sms_code)
    # ccp = CCP()
    # result = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES//60], 1)
    # if result == -1:
    #     return jsonify(errno=RET.THIRDERR, errmsg="短信验证码发送失败")

    # 把短信验证码保存到redis  注册的时候验证
    try:
        redis_store.set("SMS_" + mobile, sms_code, constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(error=RET.DATAERR, errmsg="保存六位手机验证码到redis失败")
    # 返回ok给浏览器
    return jsonify(errno=RET.OK, errmsg="短信验证码发送成功")


@passport_blu.route("/register", methods=["POST"])
def register():
    # 点击处理注册按钮的功能
    """
      处理点击注册按钮的请求


      1、获取参数，盘空
      2、对比 用户输入的短信验证码和 redis的 保存的sms_code 进行对比 ，如果不一致，return
      3、用户成功注册 (本质，有一条记录添加到数据库 User表， 创建对象User对象， 设置用户数据 ,db.session.add()   .commit())
      4、保存用户的登录信息到session中(redis)
      5、返回注册成功
      """

    parma_dict = request.json
    mobile = parma_dict.get("mobile")
    sms_code = parma_dict.get("sms_code")
    password = parma_dict.get("password")
    agree = parma_dict.get("agree")
    if not all([mobile, sms_code, password, agree]):
        return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")

    # 2、对比
    # 用户输入的短信验证码和redis的保存的sms_code
    try:
        real_sms_code = redis_store.get("SMS_" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取短信验证码失败")
    if real_sms_code.decode() != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="输入的短信验证码错误")

    # 3、用户成功注册(本质，有一条记录添加到数据库
    # User表， 创建对象User对象， 设置用户数据, db.session.add()  db.session.commit())

    user = User()
    user.mobile = mobile
    user.password = password
    user.nick_name = mobile
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()  # 事务回滚
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库操作失败")

    # 4、保存用户的登录信息到session中(redis)
    session["user_id"] = user.id
    session["mobile"] = user.mobile
    session["nick_name"] = user.nick_name

    #  返回成功
    return jsonify(errno=RET.OK, errmasg="注册成功")


@passport_blu.route("/login", methods=["POST"])
def login():
    """
    这个函数专门处理 登录  请求
    1、获取参数判空
    2、查询用户是否存在（没有注册过的用户不允许登录）
    3、校验密码是否正确
    4、保存登录状态（在session中保存登录状态）
    5、返回登录成功
    :return:
    """
    parma_dict = request.json
    mobile = parma_dict.get("mobile")
    password = parma_dict.get("password")
    # 判空
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")
    # 2、查询用户是否存在（没有注册过的用户不允许登录）

    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")
    if not user:
        return jsonify(errno=RET.USERERR, errmsg="该用户不存在")
    # 检查密码是不是 正确
    if not user.check_passowrd(password):
        return jsonify(errno=RET.DATAERR, errmsg="密码错误")


    # 登录时间
    from datetime import datetime
    user.last_login = datetime.now()
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        # 保存登录状态
    session["user_id"] = user.id
    session["mobile"] = user.mobile
    session["nick_name"] = user.nick_name

    # 5、返回登录成功
    return jsonify(errno=RET.OK, errmsg="登录成功")


@passport_blu.route("/logout")
def logout():
    # 手动删除session信息
    session.pop("user_id")
    session.pop("mobile")
    session.pop("nick_name")

    # 返回结果
    return jsonify(errno=RET.OK, errmsg="退出登录成功")